#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"
#include "my_errno.h"
#include "base64.h"

static const char *table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
struct bit_Field
{
	unsigned char a6:6;
	unsigned char a5:2;
	unsigned char a4:4;
	unsigned char a3:4;
	unsigned char a2:2;
	unsigned char a1:6;
};
union base1
{
	struct bit_Field a;
	unsigned char b[3];
};

static int ch_pos(char ch);
int base64Encode(char *dst, const char *src, int length);//编码函数
int base64Decode(char *dst, const char *src, int length);//解码函数

/*
   *Function	:ch_pos
   *Descrption	:查找字符在base64表中的位置
   *Param in	: ch 需查找字符
   *Param out	: None
   *Return		: ERROR_OK 正常返回
				  ERR_INVALID_INPUT 参数错误
*/
static int ch_pos(char ch)
{
	int n = 0;
	for(n = 0; n < 64; n++)
	{
		if(table[n] == ch)
			return n;
	}
	return -1;
}

/*
   *Function	:base64Encode
   *Descrption	:将字符串base64编码
   *Param in	: src 待编码的数据首地址
				  length 待编码的数据长度
   *Param out	: dst 编码后的字符长度
   *Return		: 正常返回编码后的字符长度
				  ERROR_OK 正常返回
				  ERR_INVALID_INPUT 参数错误
*/
int base64Encode(char *dst, const char *src, int length)
{
	if(!dst || !src || length < 0)
		return ERR_INVALID_INPUT;
	int i = 0, n = 0, num = 0;
	union base1 base64;
	n = length;
	for(i = 0; i <= n-3; i=i+3)
	{
		base64.b[2] = src[i+0];
		base64.b[1] = src[i+1];
		base64.b[0] = src[i+2];
		*(dst+num++) = *(table+(base64.a.a1));
		*(dst+num++) = *(table+((base64.a.a2)<<4) + (base64.a.a3));
		*(dst+num++) = *(table+((base64.a.a4)<<2) + (base64.a.a5));
		*(dst+num++) = *(table+(base64.a.a6));
	}
	if(n % 3 == 1)
	{
		base64.b[2] = src[length-1];
		dst[num++] = table[(base64.a.a1)];
		dst[num++] = table[((base64.a.a2)<<4)];
		dst[num++] = '=';
		dst[num++] = '=';
	}
	else if(n % 3 == 2)
	{
		base64.b[2] = src[length-2];
		base64.b[1] = src[length-1];
		dst[num++] = table[(base64.a.a1)];
		dst[num++] = table[((base64.a.a2)<<4)+(base64.a.a3)];
		dst[num++] = table[((base64.a.a4)<<2)];
		dst[num++] = '=';
	}
	dst[num] = '\0';
	return num;
}

/*
   *Function	:base64Decode
   *Descrption	:将字符串以base64方式解密
   *Param in	: src 待编码的字符串首地址
				  length 待编码的字符长度
   *Param out	: dst 解码后字符串
   *Return		: 正常返回解码后的字符长度
				  ERROR_OK 正常返回
				  ERR_INVALID_INPUT 参数错误
*/
int base64Decode(char *dst, const char *src, int length)
{
	if(!dst || !src || length%4 != 0)
		return ERR_INVALID_INPUT;
	int i;
	int num = 0;
	char b[4] = {0};
	for(i = 0; i < length - 4; i=i+4)
	{
		dst[num++] = (ch_pos(src[i])<<2)+(ch_pos(src[i+1])>>4);
		dst[num++] = (ch_pos(src[i+1])<<4)+(ch_pos(src[i+2])>>2);
		dst[num++] = (ch_pos(src[i+2])<<6)+(ch_pos(src[i+3]));
	}
	if(src[length - 2] == '=')
	{
		dst[num++] = (ch_pos(src[i])<<2)+(ch_pos(src[i+1])>>4);
	}
	else if(src[length-2] != '=' && src[length-1] == '=')
	{
		dst[num++] = (ch_pos(src[i])<<2)+(ch_pos(src[i+1])>>4);
		dst[num++] = (ch_pos(src[i+1])<<4)+(ch_pos(src[i+2])>>2);
	}
	else
	{
		dst[num++] = (ch_pos(src[i])<<2)+(ch_pos(src[i+1])>>4);
		dst[num++] = (ch_pos(src[i+1])<<4)+(ch_pos(src[i+2])>>2);
		dst[num++] = (ch_pos(src[i+2])<<6)+(ch_pos(src[i+3]));
	}
	dst[num] = '\0';
	return num;
}
